//
//  ESButton.m
//  ESFramework
//
//  Created by Elf Sundae on 4/20/14.
//  Copyright (c) 2014 www.0x123.com. All rights reserved.
//

#import "ESButton.h"
#import "UIColor+ESAdditions.h"
#import "ESDefines.h"

@implementation ESButton

+ (instancetype)button
{
        ESButton *button = [self buttonWithType:UIButtonTypeCustom];
        [button.titleLabel setFont:[UIFont boldSystemFontOfSize:16.f]];
        button.titleLabel.textAlignment = NSTextAlignmentCenter;
        
        button.buttonStyle = ESButtonStyleRoundedRect;
        button.buttonColor = ESButtonColorDefault;
        button.cornerRadius = 6.f;
        button.applyFlatStyleAutomatically = YES;
        
        return button;
}

+ (instancetype)buttonWithTitle:(NSString *)title buttonColor:(ESButtonColor)color
{
        ESButton *b = [self button];
        [b setTitle:title forState:UIControlStateNormal];
        b.buttonColor = color;
        return b;
}

+ (instancetype)buttonWithTitle:(NSString *)title
{
        return [self buttonWithTitle:title buttonColor:ESButtonColorDefault];
}

+ (instancetype)buttonWithCircleImage:(UIImage *)image
{
        ESButton *button = [self button];
        button.buttonStyle = ESButtonStyleCircle;
        [button setImage:image forState:UIControlStateNormal];
        return button;
}

+ (UIColor *)buttonColor:(ESButtonColor)color
{
        switch (color) {
                case ESButtonColorPrimary:
                        return [UIColor colorWithRed:0.00f green:0.33f blue:0.80f alpha:1.00f];
                case ESButtonColorInfo:
                        return [UIColor colorWithRed:0.18f green:0.59f blue:0.71f alpha:1.00f];
                case ESButtonColorSuccess:
                        return [UIColor colorWithRed:0.32f green:0.64f blue:0.32f alpha:1.00f];
                case ESButtonColorWarning:
                        return [UIColor colorWithRed:0.97f green:0.58f blue:0.02f alpha:1.00f];
                case ESButtonColorDanger:
                        return [UIColor colorWithRed:0.74f green:0.21f blue:0.18f alpha:1.00f];
                case ESButtonColorInverse:
                        return [UIColor colorWithRed:0.13f green:0.13f blue:0.13f alpha:1.00f];
                case ESButtonColorTwitter:
                        return [UIColor colorWithRed:0.25f green:0.60f blue:1.00f alpha:1.00f];
                case ESButtonColorFacebook:
                        return [UIColor colorWithRed:0.23f green:0.35f blue:0.60f alpha:1.00f];
                case ESButtonColorPurple:
                        return [UIColor colorWithRed:0.45f green:0.30f blue:0.75f alpha:1.00f];
                case ESButtonColorGray:
                        return [UIColor colorWithRed:0.60f green:0.60f blue:0.60f alpha:1.00f];
                case ESButtonColorRed:
                        return [UIColor colorWithRed:1.f green:0 blue:0.09 alpha:1.0f];
                case ESButtonColorDefault:
                default:
                        return [UIColor colorWithRed:0.85f green:0.85f blue:0.85f alpha:1.00f];
                        break;
        }
}

- (void)setHighlighted:(BOOL)highlighted
{
        [super setHighlighted:highlighted];
        [self setNeedsDisplay];
}

- (void)setEnabled:(BOOL)enabled
{
        [super setEnabled:enabled];
        [self setNeedsDisplay];
}

- (void)setButtonColor:(ESButtonColor)buttonColor
{
        _buttonColor = buttonColor;
        self.color = [[self class] buttonColor:buttonColor];
}

- (void)setButtonStyle:(ESButtonStyle)buttonStyle
{
        if (_buttonStyle != buttonStyle) {
                _buttonStyle = buttonStyle;
                [self setNeedsDisplay];
        }
}

- (void)setCornerRadius:(CGFloat)cornerRadius
{
        if (_cornerRadius != cornerRadius) {
                _cornerRadius = cornerRadius;
                [self setNeedsDisplay];
        }
}

- (void)setIsFlatStyle:(BOOL)isFlatStyle
{
        if (_isFlatStyle != isFlatStyle) {
                _isFlatStyle = isFlatStyle;
                [self setNeedsDisplay];
        }
}


- (void)setFrame:(CGRect)frame
{
        if (ESButtonStyleCircle == self.buttonStyle) {
                frame.size.height = frame.size.width;
        }
        [super setFrame:frame];
}

- (void)setApplyFlatStyleAutomatically:(BOOL)automatic
{
        if (_applyFlatStyleAutomatically != automatic) {
                _applyFlatStyleAutomatically = automatic;
                [self setNeedsDisplay];
        }
}

- (CGSize)sizeThatFits:(CGSize)size
{
        CGSize result = [super sizeThatFits:size];
        result.height = [self.titleLabel.font pointSize] + 16.f;
        if (ESButtonStyleRoundedRect == self.buttonStyle) {
                result.width += 20.f;
        } else if (ESButtonStyleSemi == self.buttonStyle) {
                result.width += 30.f;
        } else if (ESButtonStyleCircle == self.buttonStyle) {
                result.height = result.width;
        }
        return result;
}

- (CGSize)intrinsicContentSize {
        return [self sizeThatFits:self.bounds.size];
}

- (void)setColor:(UIColor *)color
{
        _color = color;
        if ([_color isLightColor]) {
                [self setTitleColor:[UIColor colorWithWhite:0.f alpha:.9f] forState:UIControlStateNormal];
                [self setTitleShadowColor:[UIColor colorWithWhite:1.f alpha:0.6f] forState:UIControlStateNormal];
                [self setTitleColor:[UIColor colorWithWhite:.4f alpha:.5f] forState:UIControlStateDisabled];
        } else {
                [self setTitleColor:[UIColor colorWithWhite:1.0f alpha:1.f] forState:UIControlStateNormal];
                [self setTitleShadowColor:[UIColor colorWithWhite:0.f alpha:0.6f] forState:UIControlStateNormal];
                [self setTitleColor:[UIColor colorWithWhite:1.f alpha:0.5f] forState:UIControlStateDisabled];
        }
        [self setNeedsDisplay];
}

- (void)drawRoundedStyle:(CGRect)rect context:(CGContextRef *)context
{
        UIColor *border = [self.color darkenColorWithValue:0.06f];
        
        UIColor *shadow = [self.color lightenColorWithValue:0.50f];
        CGSize shadowOffset = CGSizeMake(0.0f, 1.0f);
        CGFloat shadowBlurRadius = 2.0f;
        
        UIBezierPath *roundedRectanglePath = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0.5f, 0.5f, rect.size.width-1.0f, rect.size.height-1.0f)
                                                                        cornerRadius:self.cornerRadius];
        
        CGContextSaveGState(*context);
        
        [roundedRectanglePath addClip];
        
        CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
        UIColor *topColor = (!self.enabled) ? [self.color darkenColorWithValue:0.12f] : [self.color lightenColorWithValue:0.12f];
        
        NSArray *newGradientColors = @[(id)topColor.CGColor, (id)self.color.CGColor];
        CGFloat newGradientLocations[] = {0.0f, 1.0f};
        
        CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef)newGradientColors, newGradientLocations);
        
        CGColorSpaceRelease(colorSpace);
        
        CGContextDrawLinearGradient(*context,
                                    gradient,
                                    CGPointMake(0.0f, self.highlighted ? rect.size.height - 0.5f : 0.5f),
                                    CGPointMake(0.0f, self.highlighted ? 0.5f : rect.size.height - 0.5f), 0.0f);
        
        CGGradientRelease(gradient);
        
        CGContextRestoreGState(*context);
        
        if(!self.highlighted) {
                // Rounded Rectangle Inner Shadow
                CGRect roundedRectangleBorderRect = CGRectInset([roundedRectanglePath bounds], -shadowBlurRadius, -shadowBlurRadius);
                roundedRectangleBorderRect = CGRectOffset(roundedRectangleBorderRect, -shadowOffset.width, -shadowOffset.height);
                roundedRectangleBorderRect = CGRectInset(CGRectUnion(roundedRectangleBorderRect, [roundedRectanglePath bounds]), -1.0f, -1.0f);
                
                UIBezierPath *roundedRectangleNegativePath = [UIBezierPath bezierPathWithRect: roundedRectangleBorderRect];
                [roundedRectangleNegativePath appendPath: roundedRectanglePath];
                roundedRectangleNegativePath.usesEvenOddFillRule = YES;
                
                CGContextSaveGState(*context);
                
                CGFloat xOffset = shadowOffset.width + round(roundedRectangleBorderRect.size.width);
                CGFloat yOffset = shadowOffset.height;
                CGContextSetShadowWithColor(*context,
                                            CGSizeMake(xOffset + copysign(0.1f, xOffset), yOffset + copysign(0.1f, yOffset)),
                                            shadowBlurRadius,
                                            shadow.CGColor);
                
                [roundedRectanglePath addClip];
                CGAffineTransform transform = CGAffineTransformMakeTranslation(-round(roundedRectangleBorderRect.size.width), 0.0f);
                [roundedRectangleNegativePath applyTransform: transform];
                [[UIColor grayColor] setFill];
                [roundedRectangleNegativePath fill];
                
                CGContextRestoreGState(*context);
        }
        
        [border setStroke];
        roundedRectanglePath.lineWidth = 1.0f;
        [roundedRectanglePath stroke];
}

- (void)_drawBButtonStyleV3InRect:(CGRect)rect withContext:(CGContextRef *)context
{
        CGContextSaveGState(*context);
        
        UIColor *fill = (!self.highlighted) ? self.color : [self.color darkenColorWithValue:0.06f];
        if(!self.enabled)
                [fill desaturatedColorToPercentSaturation:0.60f];
        
        CGContextSetFillColorWithColor(*context, fill.CGColor);
        
        UIColor *border = (!self.highlighted) ? [self.color darkenColorWithValue:0.06f] : [self.color darkenColorWithValue:0.12f];
        if(!self.enabled)
                [border desaturatedColorToPercentSaturation:0.60f];
        
        CGContextSetStrokeColorWithColor(*context, border.CGColor);
        
        CGContextSetLineWidth(*context, 1.0f);
        
        UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0.5f, 0.5f, rect.size.width-1.0f, rect.size.height-1.0f)
                                                        cornerRadius:self.cornerRadius];
        
        CGContextAddPath(*context, path.CGPath);
        CGContextDrawPath(*context, kCGPathFillStroke);
        
        CGContextRestoreGState(*context);
}

- (void)drawCircleStyle:(CGRect)rect context:(CGContextRef *)context
{
        CAShapeLayer *maskLayer = [CAShapeLayer layer];
        maskLayer.frame = self.imageView.bounds;
        maskLayer.path = [UIBezierPath bezierPathWithRoundedRect:self.imageView.bounds cornerRadius:self.cornerRadius].CGPath;
        self.imageView.layer.mask = maskLayer;
}

- (void)drawRect:(CGRect)rect
{
        [super drawRect:rect];

        CGContextRef context = UIGraphicsGetCurrentContext();
        if (!context) return;
        
        if (ESButtonStyleSemi == self.buttonStyle ||
            ESButtonStyleCircle == self.buttonStyle) {
                self.cornerRadius = self.bounds.size.width / 2.f;
        }
        
        if (ESButtonStyleCircle == self.buttonStyle && self.imageView.image) {
                [self drawCircleStyle:rect context:&context];
        } else {
                if (self.isFlatStyle ||
                    (self.applyFlatStyleAutomatically && ESOSVersionIsAbove7())) {
                        [self _drawBButtonStyleV3InRect:rect withContext:&context];
                } else {
                        [self drawRoundedStyle:rect context:&context];
                }
        }
}

@end
